﻿using DNFImagePacks2Manager.Helpers;
using DNFImagePacks2Manager.Models;
using Microsoft.UI;
using Microsoft.UI.Dispatching;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Media;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Threading.Tasks;
using Windows.Storage;

namespace DNFImagePacks2Manager.Pages
{
    public sealed partial class ProcessLoadPage : Page
    {
        private readonly DispatcherQueue _dispatcherQueue;

        public ProcessLoadPage()
        {
            InitializeComponent();
            _dispatcherQueue = DispatcherQueue.GetForCurrentThread();
        }

        public async Task StartImportTask(List<StorageFile> files)
        {
            if (files == null) {
                await DispatchToUI(() =>
                {
                    TitleTextBlock.Text = $"获取文件列表失败，请重试";
                });
                return;
            }

            void progressCallback(string title, string message)
            {
                _dispatcherQueue.TryEnqueue(() =>
                {
                    switch (title)
                    {
                        case "进度":
                            FileProgressText.Text = $"处理文件: {message}";
                            if (message.Contains('/') &&
                                int.TryParse(message.Split('/')[0], out int current) &&
                                int.TryParse(message.Split('/')[1], out int total))
                            {
                                FileProgressBar.Value = Math.Round((double)current / total * 100, 1);
                            }
                            break;

                        case "当前文件":
                            CurrentFileText.Text = $"当前文件: {message}";
                            break;

                        case "解压进度":
                            ExtractProgressText.Text = $"解压进度: {message}";
                            if (message.Contains('/') &&
                                int.TryParse(message.Split('/')[0], out int extractCurrent) &&
                                int.TryParse(message.Split('/')[1], out int extractTotal))
                            {
                                ExtractProgressBar.Value = Math.Round((double)extractCurrent / extractTotal * 100, 1);
                            }
                            break;

                        case "压缩包开始":
                            AddLog($"[压缩包] 开始处理：{message}", "Blue");
                            ExtractProgressPanel.Visibility = Visibility.Visible;
                            break;

                        case "压缩包结束":
                            AddLog($"[压缩包] 处理完成：{message}", "Blue");
                            ExtractProgressPanel.Visibility = Visibility.Collapsed;
                            break;

                        case "完成":
                            AddLog($"✅ {message}", "Green");
                            break;

                        case "错误":
                            AddLog($"❌ 错误：{message}", "Red");
                            break;

                        case "日志":
                            AddLog(message, message.Contains('√') ? "Green" : "Red");
                            break;
                    }

                    LogScrollViewer.ScrollToVerticalOffset(LogPanel.ActualHeight);
                });
            }

            bool result = await ProcessFiles(files, progressCallback);
            await DispatchToUI(() =>
            {
                TitleTextBlock.Text = "文件处理完毕";
                CurrentFileText.Text = $"当前文件: 无";
            });
        }

        private async Task<bool> ProcessFiles(List<StorageFile> files, Action<string, string> progressCallback)
        {
            try
            {

                if (!LocalStorageHelper.IsSetDNFPath())
                {
                    progressCallback?.Invoke("错误", "DNF文件夹路径未配置或不存在");
                    return false;
                }

                int totalFiles = files.Count;
                for (int i = 0; i < totalFiles; i++)
                {
                    var file = files[i];
                    string fileName = file.Name;
                    string progressInfo = $"{i + 1}/{totalFiles}";

                    progressCallback?.Invoke("进度", progressInfo);
                    progressCallback?.Invoke("当前文件", fileName);

                    try
                    {
                        if (fileName.EndsWith(".csm", StringComparison.OrdinalIgnoreCase))
                        {
                            string result = await ProcessCustomFile(file);
                            progressCallback?.Invoke("日志", result);
                            continue;
                        }

                        if (fileName.EndsWith(".csm2", StringComparison.OrdinalIgnoreCase))
                        {
                            string result = await ProcessCustomFile(file);
                            progressCallback?.Invoke("日志", result);
                            continue;
                        }

                        if (fileName.EndsWith(".bk2", StringComparison.OrdinalIgnoreCase))
                        {
                            string result = ProcessBKFile(file);
                            progressCallback?.Invoke("日志", result);
                            continue;
                        }

                        if (NPKHelper.FilenameCheckNPKFile(fileName))
                        {
                            string result = await ProcessNPKFileAsync(file);
                            progressCallback?.Invoke("日志", result);
                            continue;
                        }

                        if (ArchiveHelper.IsArchiveFile(fileName))
                        {
                            await ProcessArchiveFile(file, progressCallback);
                            continue;
                        }

                        progressCallback?.Invoke("日志", $"× {fileName} 无效的文件类型");
                    }
                    catch (Exception ex)
                    {
                        progressCallback?.Invoke("日志", $"× {fileName} 添加失败, 异常的错误: {ex.Message}");
                    }
                }

                progressCallback?.Invoke("完成", "文件添加完成!");
                return true;
            }
            catch (Exception ex)
            {
                progressCallback?.Invoke("错误", $"添加文件失败: {ex.Message}");
                return false;
            }
        }
        private async Task<string> ProcessCustomFile(StorageFile file)
        {
            string name = file.DisplayName;

            try
            {
                string customFolder = CustomHelper.GetCustomFolder();
                string customFile = Path.Combine(customFolder, file.Name);

                if (File.Exists(customFile))
                {
                    return $"× 个性化配置 {name} 已存在，已跳过";
                }

                await file.CopyAsync(await StorageFolder.GetFolderFromPathAsync(customFolder));
                return $"√ 个性化配置 {name} 导入成功";
            }
            catch (Exception ex)
            {
                return $"× 个性化配置 {name} 导入失败: {ex.Message}";
            }
        }

        private async Task<string> ProcessNPKFileAsync(StorageFile file)
        {
            string name = file.DisplayName;

            try
            {
                NPKItemBase item;

                int type = NPKHelper.GetNPKType(file.Path);

                switch (type)
                {
                    case 2:
                        item = new NPKItemSound(file.Name);
                        break;
                    case 1:
                        item = new NPKItemImage(file.Name);
                        break;
                    case 0:
                    default:
                        if (name.Contains("sound"))
                        {
                            item = new NPKItemSound(file.Name);
                        }
                        else
                        {
                            item = new NPKItemImage(file.Name);
                        }
                        break;
                }

                string display = item.DisplayName;

                if (item.IsFileExist)
                {
                    return $"× 补丁文件 {display} 已存在，已跳过";
                }

                await file.CopyAsync(await StorageFolder.GetFolderFromPathAsync(item.BasePath), item.EnableName, NameCollisionOption.FailIfExists);
                return $"√ 补丁文件 {display} 安装成功";
            }
            catch (Exception ex)
            {
                return $"× 补丁文件 {name} 安装失败: {ex.Message}";
            }
        }

        private string ProcessBKFile(StorageFile file)
        {

            bool result = BKHelper.SaveBKFile(file.Path, out string message);

            if (result)
            {
                return $"√ 补丁文件 {file.DisplayName} 安装成功";
            }
            else
            {
                return $"× 补丁文件 {file.DisplayName} 安装失败: {message}";
            }
        }

        private async Task ProcessArchiveFile(StorageFile archiveFile, Action<string, string>? progressCallback)
        {
            string fileName = archiveFile.Name;
            progressCallback?.Invoke("压缩包开始", $"{fileName}");

            try
            {
                string archivePath = archiveFile.Path;
                int extractResult = ArchiveHelper.ExtractArchive(archivePath, progressCallback);
                switch (extractResult)
                {
                    case 2:
                        progressCallback?.Invoke("日志", $"× {fileName} 解压失败，压缩文件需要密码");
                        await ExtractEncryptedArchive(archiveFile, progressCallback);
                        break;
                    case 0:
                        progressCallback?.Invoke("日志", $"× {fileName} 解压失败");
                        break;
                }

                progressCallback?.Invoke("压缩包结束", $"{fileName}");
            }
            catch (Exception ex)
            {
                progressCallback?.Invoke("日志", $"× {fileName} 压缩包处理失败: {ex.Message}");
            }
        }

        private async Task ExtractEncryptedArchive(StorageFile archiveFile, Action<string, string>? progressCallback)
        {
            string password = "";
            string fileName = archiveFile.Name;
            string title = $"{fileName} 需要密码";

            var tcs = new TaskCompletionSource<bool>();

            await DispatchToUI(async () =>
            {
                while (true)
                {
                    TextBox inputTextBox = new()
                    {
                        Text = password,
                        Margin = new Thickness(0, 10, 0, 0)
                    };

                    StackPanel stackPanel = new();
                    stackPanel.Children.Add(inputTextBox);

                    inputTextBox.SelectAll();

                    ContentDialogResult result = await DialogHelper.ShowConfirmDialog(this, title, stackPanel);

                    if (result == ContentDialogResult.Primary)
                    {
                        password = inputTextBox.Text;

                        var extractResult = await Task.Run(() =>
                            ArchiveHelper.ExtractArchive(archiveFile.Path, progressCallback, password)
                        );

                        switch (extractResult)
                        {
                            case 2:
                                progressCallback?.Invoke("日志", $"× {fileName} 解压失败，密码错误");
                                title = $"{fileName} 密码错误，请重新输入";
                                break;
                            case 1:
                                progressCallback?.Invoke("日志", $"√ {fileName} 解压成功");
                                tcs.SetResult(true);
                                return;
                            case 0:
                                progressCallback?.Invoke("日志", $"× {fileName} 解压失败");
                                tcs.SetResult(true);
                                return;
                        }
                    }
                    else
                    {
                        progressCallback?.Invoke("日志", $"× {fileName} 用户取消解压");
                        tcs.SetResult(true);
                        return;
                    }
                }
            });

            await tcs.Task;
        }

        private Task DispatchToUI(Action uiAction)
        {
            var tcs = new TaskCompletionSource<bool>();
            if (_dispatcherQueue.TryEnqueue(() =>
            {
                try
                {
                    uiAction();
                    tcs.SetResult(true);
                }
                catch (Exception ex)
                {
                    tcs.SetException(ex);
                }
            }))
            {
                return tcs.Task;
            }
            else
            {
                return Task.FromException(new InvalidOperationException("UI 线程已关闭，无法更新进度"));
            }
        }

        private void AddLog(string content, string color)
        {
            var logItem = new TextBlock
            {
                Text = $"[{DateTime.Now:HH:mm:ss}] {content}",
                Margin = new Thickness(0, 3, 0, 3),
                TextWrapping = TextWrapping.Wrap,
                FontSize = 12
            };

            switch (color.ToLower())
            {
                case "red":
                    logItem.Foreground = new SolidColorBrush(Colors.Red);
                    break;
                case "green":
                    logItem.Foreground = new SolidColorBrush(Colors.Green);
                    break;
                case "blue":
                    logItem.Foreground = new SolidColorBrush(Colors.Blue);
                    break;
                default:
                    logItem.Foreground = new SolidColorBrush(Colors.Gray);
                    break;
            }

            LogPanel.Children.Add(logItem);
        }
    }
}
